package com.lineage.server.world;

import com.lineage.server.model.Instance.L1EffectInstance;
import com.lineage.server.model.L1Character;
import com.lineage.server.model.L1Location;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.map.L1Map;
import com.lineage.server.types.Point;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class WorldEffect {
  private static final Log _log = LogFactory.getLog(WorldEffect.class);
  
  private static WorldEffect _instance;
  
  private final ConcurrentHashMap<Integer, L1EffectInstance> _isEff;
  
  private Collection<L1EffectInstance> _allEffValues;
  
  public static WorldEffect get() {
    if (_instance == null)
      _instance = new WorldEffect(); 
    return _instance;
  }
  
  private WorldEffect() {
    this._isEff = new ConcurrentHashMap<>();
  }
  
  public Collection<L1EffectInstance> all() {
    try {
      Collection<L1EffectInstance> vs = this._allEffValues;
      return (vs != null) ? vs : (this._allEffValues = Collections.unmodifiableCollection(this._isEff.values()));
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
  
  public ConcurrentHashMap<Integer, L1EffectInstance> map() {
    return this._isEff;
  }
  
  public void put(Integer key, L1EffectInstance value) {
    try {
      this._isEff.put(key, value);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void remove(Integer key) {
    try {
      this._isEff.remove(key);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public boolean isEffect(L1Location loc, int npcid) {
    Iterator<L1EffectInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1EffectInstance element = iter.next();
      if (loc.getMapId() != element.getMap().getId())
        continue; 
      if (npcid != element.getNpcId())
        continue; 
      if (loc.isSamePoint((Point)element.getLocation()))
        return true; 
    } 
    return false;
  }
  
  public ArrayList<L1EffectInstance> getVisibleEffect(L1Location loc) {
    ArrayList<L1EffectInstance> result = new ArrayList<>();
    Iterator<L1EffectInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1EffectInstance element = iter.next();
      if (loc.getMapId() != element.getMap().getId())
        continue; 
      if (!loc.isSamePoint((Point)element.getLocation()))
        continue; 
      result.add(element);
    } 
    return result;
  }
  
  public ArrayList<L1EffectInstance> getVisibleEffect(L1EffectInstance src) {
    L1Map map = src.getMap();
    L1Location l1Location = src.getLocation();
    ArrayList<L1EffectInstance> result = new ArrayList<>();
    Iterator<L1EffectInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1EffectInstance element = iter.next();
      if (element.equals(src))
        continue; 
      if (map.getId() != element.getMap().getId())
        continue; 
      if (src.getNpcId() != element.getNpcId())
        continue; 
      if (!l1Location.isSamePoint((Point)element.getLocation()))
        continue; 
      result.add(element);
    } 
    return result;
  }
  
  public int getVisibleCount(L1EffectInstance src) {
    L1Map map = src.getMap();
    L1Location l1Location = src.getLocation();
    int count = 0;
    Iterator<L1EffectInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1EffectInstance element = iter.next();
      if (element.equals(src))
        continue; 
      if (map != element.getMap())
        continue; 
      if (!l1Location.isInScreen((Point)element.getLocation()) || src.getNpcId() != element.getNpcId())
        continue; 
      count++;
    } 
    return count;
  }
  
  public ArrayList<L1Character> getFirewall(L1EffectInstance firewall) {
    L1Map map = firewall.getMap();
    L1Location l1Location = firewall.getLocation();
    ArrayList<L1Character> result = new ArrayList<>();
    ArrayList<L1Object> mapSrc = World.get().getVisibleObjects((L1Object)firewall, 2);
    if (mapSrc == null) {
      _log.error("游戏世界储存中心并未建立该地图编号资料档案: " + map.getId());
      return result;
    } 
    if (mapSrc.isEmpty())
      return result; 
    if (World.get().findObject(firewall.getId()) == null)
      return result; 
    if (World.get().findObject(firewall.getMaster().getId()) == null)
      return result; 
    if (firewall.destroyed())
      return result; 
    if (firewall.getMaster() == null)
      return result; 
    Iterator<L1Object> iterator = mapSrc.iterator();
    while (iterator.hasNext()) {
      L1Object element = iterator.next();
      if (!(element instanceof L1Character))
        continue; 
      if (firewall.getMaster().equals(element))
        continue; 
      L1Character cha = (L1Character)element;
      if (cha.isDead())
        continue; 
      int r = l1Location.getTileLineDistance((Point)element.getLocation());
      if (r > 1)
        continue; 
      result.add((L1Character)element);
    } 
    return result;
  }
}
